//------------------------------------------------------------------------------
// <copyright file="WebAdminPage.cs" company="Microsoft">
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// </copyright>
//------------------------------------------------------------------------------

using System;
using System.Collections;
using System.Configuration;
using System.Reflection;
using System.Security.Permissions;
using System.Web;
using System.Web.Configuration;
using System.Web.Hosting;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace Salient.Web.Administration
{
    [AspNetHostingPermission(SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]
    [AspNetHostingPermission(SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal)]
    public class WebAdminPage : Page
    {
        private const string APP_PATH = "WebAdminApplicationPath";
        private const string APP_PHYSICAL_PATH = "WebAdminPhysicalPath";
        private const string CURRENT_EXCEPTION = "WebAdminCurrentException";
        private const string CURRENT_PROVIDER = "WebAdminCurrentProvider";
        private const string CURRENT_ROLE = "WebAdminCurrentRoleName";
        private const string CURRENT_USER = "WebAdminCurrentUser";
        private const string CURRENT_USER_COLLECTION = "WebAdminUserCollection";
        private const string URL_STACK = "WebAdminUrlStack";
        private string _directionality;

        public WebAdminRemotingManager RemotingManager
        {
            get { return (WebAdminRemotingManager) Session["WebAdminRemotingManager"]; }
        }


        public string ApplicationPath
        {
            get { return (string) Session[APP_PATH]; }
        }

        protected virtual bool CanSetApplicationPath
        {
            get { return false; }
        }

        protected string CurrentProvider
        {
            get
            {
                object obj = Session[CURRENT_PROVIDER];
                if (obj != null)
                {
                    return (string) Session[CURRENT_PROVIDER];
                }
                return String.Empty;
            }
            set { Session[CURRENT_PROVIDER] = value; }
        }

        protected string CurrentRequestUrl
        {
            get
            {
                var stack = (Stack) Session[URL_STACK];
                if (stack != null && stack.Count > 0)
                {
                    return (string) stack.Peek();
                }
                return string.Empty;
            }
        }

        protected string CurrentRole
        {
            get
            {
                object obj = Session[CURRENT_ROLE];
                if (obj != null)
                {
                    return (string) Session[CURRENT_ROLE];
                }
                return String.Empty;
            }
            set { Session[CURRENT_ROLE] = value; }
        }

        protected string CurrentUser
        {
            get
            {
                object obj = Session[CURRENT_USER];
                if (obj != null)
                {
                    return (string) Session[CURRENT_USER];
                }
                return String.Empty;
            }
            set { Session[CURRENT_USER] = value; }
        }

        public string Directionality
        {
            get
            {
                if (String.IsNullOrEmpty(_directionality))
                {
                    _directionality =
                        ((string) GetGlobalResourceObject("GlobalResources", "HtmlDirectionality")).ToLower();
                }
                return _directionality;
            }
        }

        public HorizontalAlign DirectionalityHorizontalAlign
        {
            get
            {
                if (Directionality == "rtl")
                {
                    return HorizontalAlign.Right;
                }
                else
                {
                    return HorizontalAlign.Left;
                }
            }
        }

        public Hashtable UserCollection
        {
            get
            {
                var table = (Hashtable) Session[CURRENT_USER_COLLECTION];
                if (table == null)
                {
                    Session[CURRENT_USER_COLLECTION] = table = new Hashtable();
                }
                return table;
            }
        }

        public NavigationBar NavigationBar { get; set; }

        public string UnderscoreProductVersion
        {
            get { return Environment.Version.ToString(3).Replace(".", "_"); }
        }

        public object CallWebAdminHelperMethod(bool isMembership, string methodName, object[] parameters,
                                               Type[] paramTypes)
        {
            object returnObject = null;
            object tempObject = null;

            tempObject = RemotingManager.ConfigurationHelperInstance;
            if (tempObject != null)
            {
                string methodName2 = string.Empty;
                string typeFullName = WebAdminRemotingManager.AssemblyVersionString;
                if (isMembership)
                {
                    methodName2 = "CallMembershipProviderMethod";
                }
                else
                {
                    methodName2 = "CallRoleProviderMethod";
                }
                Type tempType = Type.GetType(typeFullName);

                BindingFlags allBindingFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
                MethodInfo method = tempType.GetMethod(methodName2, allBindingFlags);
                if (method != null)
                {
                    var newParameters = new object[] {methodName, parameters, paramTypes};
                    try
                    {
                        var returnArrayObj = (object[]) method.Invoke(tempObject, newParameters);
                        if (returnArrayObj != null)
                        {
                            returnObject = returnArrayObj[0];
                        }
                    }
                    catch (Exception ex)
                    {
                        if (ex.InnerException != null)
                        {
                            if (ex.InnerException.InnerException != null)
                            {
                                throw new WebAdminException(ex.InnerException.InnerException.Message);
                            }
                            else
                            {
                                throw new WebAdminException(ex.InnerException.Message);
                            }
                        }
                        else
                        {
                            throw new WebAdminException(ex.Message);
                        }
                    }
                }
            }

            return returnObject;
        }

        public VirtualDirectory GetVirtualDirectory(string virtualDir)
        {
            return RemotingManager.GetVirtualDirectory(virtualDir);
        }

        public void SaveConfig(System.Configuration.Configuration config)
        {
            RemotingManager.ShutdownTargetApplication();

            // check if session expired
            if (String.IsNullOrEmpty(ApplicationPath) || String.IsNullOrEmpty((string) Session[APP_PHYSICAL_PATH]))
            {
                Server.Transfer("~/home2.aspx");
            }

            config.Save(ConfigurationSaveMode.Minimal);
        }

        public static Exception GetCurrentException(HttpContext c)
        {
            return (Exception) c.Session[CURRENT_EXCEPTION];
        }

        public static void SetCurrentException(HttpContext c, Exception ex)
        {
            c.Session[CURRENT_EXCEPTION] = ex;
        }

        protected void ClearBadStackPage()
        {
            var stack = (Stack) Session[URL_STACK];
            if (stack == null || stack.Count < 2)
            {
                return;
            }
            stack.Pop(); // current url
            stack.Pop(); // prev url
            // push current url back on stack.
            if (string.Compare(CurrentRequestUrl, Request.CurrentExecutionFilePath) != 0)
            {
                PushRequestUrl(Request.CurrentExecutionFilePath);
            }
        }

        public void ClearUserCollection()
        {
            Session[CURRENT_USER_COLLECTION] = null;
        }

        public static string GetParentPath(string path)
        {
            if (String.IsNullOrEmpty(path) || path[0] != '/')
                return null;

            int index = path.LastIndexOf('/');
            if (index < 0)
                return null;

            // parent for the root app is machine.config (null)
            if (path == "/")
                return null;

            string returnPath = path.Substring(0, index);
            if (returnPath.Length == 0 || returnPath == "/")
            {
                // for cassini, if returning /
                // then return null instead.
                returnPath = null;
            }

            return returnPath;
        }

        protected string GetQueryStringAppPath()
        {
            return Request.QueryString["applicationUrl"];
        }

        protected string GetQueryStringPhysicalAppPath()
        {
            return Request.QueryString["applicationPhysicalPath"];
        }

        public bool IsRoleManagerEnabled()
        {
            try
            {
                RoleManagerSection roleSection = null;
                System.Configuration.Configuration config = OpenWebConfiguration(ApplicationPath);
                roleSection = (RoleManagerSection) config.GetSection("system.web/roleManager");
                return roleSection.Enabled;
            }
            catch
            {
                return false;
            }
        }

        public bool IsRuleValid(BaseValidator placeHolderValidator, RadioButton userRadio, TextBox userName,
                                RadioButton roleRadio, DropDownList roles)
        {
            if (userRadio.Checked && userName.Text.Trim().Length == 0)
            {
                placeHolderValidator.ErrorMessage =
                    ((string) GetGlobalResourceObject("GlobalResources", "NonemptyUser"));
                placeHolderValidator.IsValid = false;
                return false;
            }
            if (roleRadio.Checked && roles.SelectedItem == null)
            {
                placeHolderValidator.ErrorMessage =
                    ((string) GetGlobalResourceObject("GlobalResources", "NonemptyRole"));
                placeHolderValidator.IsValid = false;
                return false;
            }
            if (userRadio.Checked)
            {
                string userNameString = userName.Text.Trim();
                if (-1 != userNameString.IndexOf('*'))
                {
                    placeHolderValidator.ErrorMessage =
                        ((string) GetGlobalResourceObject("GlobalResources", "InvalidRuleName"));
                    placeHolderValidator.IsValid = false;
                    return false;
                }
            }
            return true;
        }

        public bool IsWindowsAuth()
        {
            System.Configuration.Configuration config = OpenWebConfiguration(ApplicationPath);
            var auth = (AuthenticationSection) config.GetSection("system.web/authentication");
            return auth.Mode == AuthenticationMode.Windows;
        }

        protected void ItemDataBound(object sender, DataGridItemEventArgs e)
        {
            ListItemType itemType = e.Item.ItemType;
            if ((itemType == ListItemType.Pager) ||
                (itemType == ListItemType.Header) ||
                (itemType == ListItemType.Footer))
            {
                return;
            }
            foreach (Control c in e.Item.Cells[0].Controls)
            {
                var button = c as LinkButton;
                if (button == null)
                {
                    continue;
                }
                e.Item.Attributes["onclick"] = GetPostBackClientHyperlink(button, String.Empty);
            }
        }

        public System.Configuration.Configuration OpenWebConfiguration(string path)
        {
            return OpenWebConfiguration(path, false);
        }

        public System.Configuration.Configuration OpenWebConfiguration(string path, bool getWebConfigForSubDir)
        {
            var appPhysPath = (string) Session[APP_PHYSICAL_PATH];
            return OpenWebConfiguration(path, appPhysPath, getWebConfigForSubDir);
        }

        private System.Configuration.Configuration OpenWebConfiguration(string path, string appPhysPath,
                                                                        bool getWebConfigForSubDir)
        {
            // check if session expired
            if (String.IsNullOrEmpty(ApplicationPath) || String.IsNullOrEmpty((string) Session[APP_PHYSICAL_PATH]))
            {
                Server.Transfer("~/home2.aspx");
            }

            if (String.IsNullOrEmpty(path))
            {
                return WebConfigurationManager.OpenWebConfiguration(null);
            }

            var appVPath = (string) Session[APP_PATH];
            if (!getWebConfigForSubDir)
            {
                appVPath = path;
            }

            var fileMap = new WebConfigurationFileMap();
            fileMap.VirtualDirectories.Add(appVPath, new VirtualDirectoryMapping(appPhysPath, true));
            return WebConfigurationManager.OpenMappedWebConfiguration(fileMap, path);
        }

        protected override void OnInit(EventArgs e)
        {
            string applicationPath = ApplicationPath;
            string queryStringAppPath = GetQueryStringAppPath();
            string applicationPhysicalPath = GetQueryStringPhysicalAppPath();
            string requestAppPath = HttpContext.Current.Request.ApplicationPath;
            string currExFilePath = Request.CurrentExecutionFilePath;

            if (applicationPhysicalPath != null)
            {
                string webAdminVersion = "aspnet_webadmin\\" + UnderscoreProductVersion + "\\";
                if (applicationPhysicalPath.EndsWith(webAdminVersion))
                {
                    queryStringAppPath = requestAppPath;
                }
            }

            SetApplicationPath();

            if (string.Compare(CurrentRequestUrl, Request.CurrentExecutionFilePath) != 0)
            {
                PushRequestUrl(Request.CurrentExecutionFilePath);
            }

            base.OnInit(e);
        }

        protected void PopulateRepeaterDataSource(Repeater repeater)
        {
            // display alphabet row only if language is has Alphabet resource
            var arr = new ArrayList();
            var chars = ((string) GetGlobalResourceObject("GlobalResources", "Alphabet"));
            foreach (String s in chars.Split(';'))
            {
                arr.Add(s);
            }
            if (arr.Count == 0)
            {
                repeater.Visible = false;
            }
            else
            {
                arr.Add(GetGlobalResourceObject("GlobalResources", "All"));
                repeater.DataSource = arr;
                repeater.Visible = true;
            }
        }

        protected string PopPrevRequestUrl()
        {
            var stack = (Stack) Session[URL_STACK];
            if (stack == null || stack.Count < 2)
            {
                return string.Empty;
            }
            stack.Pop(); // discard current url
            return (string) stack.Pop();
        }

        protected void PushRequestUrl(string s)
        {
            var stack = (Stack) Session[URL_STACK];
            if (stack == null)
            {
                Session[URL_STACK] = stack = new Stack();
            }
            stack.Push(s);
        }

        protected void ReturnToPreviousPage(object sender, EventArgs e)
        {
            string prevRequest = PopPrevRequestUrl();
            Response.Redirect(prevRequest, false); // note: string.Empty ok here.
        }

        protected void RetrieveLetter(object sender, RepeaterCommandEventArgs e, GridView dataGrid)
        {
            RetrieveLetter(sender, e, dataGrid, (string) GetGlobalResourceObject("GlobalResources", "All"));
        }

        protected void RetrieveLetter(object sender, RepeaterCommandEventArgs e, GridView dataGrid, string all)
        {
            RetrieveLetter(sender, e, dataGrid, all, null);
        }

        protected void RetrieveLetter(object sender, RepeaterCommandEventArgs e, GridView dataGrid, string all,
                                      MembershipUserCollection users)
        {
            dataGrid.PageIndex = 0;
            int total = 0;
            string arg = e.CommandArgument.ToString();

            if (arg == all)
            {
                dataGrid.DataSource = (users == null)
                                          ? CallWebAdminHelperMethod(true, "GetAllUsers",
                                                                     new object[] {0, Int32.MaxValue, total},
                                                                     new[]
                                                                         {
                                                                             typeof (int), typeof (int),
                                                                             Type.GetType("System.Int32&")
                                                                         })
                                          : users;
            }
            else
            {
                dataGrid.DataSource = CallWebAdminHelperMethod(true, "FindUsersByName",
                                                               new object[]
                                                                   {arg + "%", 0, Int32.MaxValue, total},
                                                               new[]
                                                                   {
                                                                       typeof (string), typeof (int), typeof (int),
                                                                       Type.GetType("System.Int32&")
                                                                   });
            }
            dataGrid.DataBind();
        }

        protected void SetApplicationPath()
        {
            if (!VerifyAppValid())
            {
                Server.Transfer("~/error.aspx");
            }
        }

        // At point when app is set, verify it is valid (i.e., permissions are proper and app exists).
        private bool VerifyAppValid()
        {
            // check if session expired
            if (String.IsNullOrEmpty(ApplicationPath) || String.IsNullOrEmpty((string) Session[APP_PHYSICAL_PATH]))
            {
                Server.Transfer("~/home2.aspx");
            }

            try
            {
                System.Configuration.Configuration config = OpenWebConfiguration(ApplicationPath);
                SaveConfig(config);
            }
            catch (Exception e)
            {
                var ex = new Exception(e.ToString());
                SetCurrentException(Context, ex);
                return false;
            }
            return true;
        }
    }
}